﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
using IronPython.Modules;
using Trinity.Components.Combat;
using Trinity.Components.Combat.Resources;
using Trinity.DbProvider;
using Trinity.Framework;
using Trinity.Framework.Actors.ActorTypes;
using Trinity.Framework.Helpers;
using Trinity.Framework.Objects;
using Trinity.Routines.Crusader;
using Trinity.Settings;
using Trinity.UI;
using Zeta.Common;
using Zeta.Game;
using Zeta.Game.Internals.Actors;
using Zeta.Game.Internals.SNO;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using Trinity.Framework.Reference;

namespace Trinity.Routines.Wizard
{
    public sealed class MyPralysisArchonBlizzard : WizardBase, IRoutine
    {

        #region Definition
        public string DisplayName => "塔拉夏5+维尔3 暴风雪电疗1.0.1";
        public string Description => "暗黑插件爱好者协会";
        public string Author => "不正常人类研究所-殉道者，killsb修复";
        public string Version => "1.0.1";
        public string Url => "http://www.demonbuddy.cn/thread-11818-1-1.html";

        #region Build Definition
        public Build BuildRequirements => new Build
        {
            Sets = new Dictionary<Set, SetBonus>
            {
                { Sets.TalRashasElements, SetBonus.Third },
                { Sets.VyrsAmazingArcana, SetBonus.Second }
            },
            Skills = new Dictionary<Skill, Rune>
            {
                { Skills.Wizard.Archon, Runes.Wizard.Combustion },
                { Skills.Wizard.MagicWeapon, Runes.Wizard.Deflection },
                { Skills.Wizard.BlackHole, Runes.Wizard.Spellsteal },
                { Skills.Wizard.EnergyArmor, Runes.Wizard.ForceArmor },
                { Skills.Wizard.Blizzard, Runes.Wizard.FrozenSolid},
                { Skills.Wizard.ArcaneTorrent, Runes.Wizard.StaticDischarge}
            },
            Items = new List<Item>
            {
                Legendary.ManaldHeal,
                Legendary.ObsidianRingOfTheZodiac,
                Legendary.RingOfRoyalGrandeur,
                Legendary.Ingeom
            }
        };

        public override KiteMode KiteMode => IsArchonActive ? KiteMode.Never : KiteMode.Elites | KiteMode.Bosses;
        public override float KiteDistance => 25f;
        public override Func<bool> ShouldIgnoreAvoidance => () => IsArchonActive;
        #endregion


        private Vector3 lastBlackHolePosition = Vector3.Zero;
        private Vector3 lastBlizzardPosition = Vector3.Zero;
        public TrinityPower GetOffensivePower()
        {
            // 锁定奥拉什
            var target = Core.Actors.Actors.Where(u => u.ActorSnoId == 360636).ToList().FirstOrDefault();

            if (target == null)
                target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget;

            if (IsArchonActive)
            {
                if (GetArchonBuffRemaining() < 500 && Skills.Wizard.ArchonTeleport.TimeSinceUse > 500)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 30, 50, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("御法者快消失");
                        return Teleport(safeSpot);
                    }
                }

                // 如果被AOE击中，传送到安全区域
                if (!Core.Buffs.HasInvulnerableShrine && Core.Avoidance.InAvoidance(Core.Player.Position))
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 25, 45, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("AOE 目标为中心");
                        return Teleport(safeSpot);
                    }

                    safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 15, 40, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("AOE 自己为中心");
                        return Teleport(safeSpot);
                    }
                }

                //// 进神目指环
                //TrinityPower buffed;
                //if (!Player.IsMoving && PositionUtil.TryTeleportBuffedPostion(out buffed, 50, 10, 15, target.Position))
                //    return buffed;

                // 法能护体消失后传送到安全位置
                if (!Core.Buffs.HasInvulnerableShrine && IsArchonGalvanizingWardGone() && Skills.Wizard.ArchonTeleport.TimeSinceUse > 2000)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 35, 50, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("没有法能护体");
                        return Teleport(safeSpot);
                    }
                }

                // 无护盾状态，传送走
                if (!Core.Buffs.HasInvulnerableShrine && Player.CurrentHealthPct < 1 && Skills.Wizard.ArchonTeleport.TimeSinceUse > 1500)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 35, 50, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("没有护盾");
                        return Teleport(safeSpot);
                    }
                }

                if (target.IsBoss && target.Distance < 25)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 40, 60, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("25码boss");
                        return Teleport(safeSpot);
                    }
                }

                if (target.IsElite && target.Distance < 25)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 30, 50, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("25码boss");
                        return Teleport(safeSpot);
                    }
                }

                if (target.IsElite && target.Distance < 25)
                {
                    var safeSpot = Vector3.Zero;
                    if (Core.Avoidance.Avoider.TryGetSafeSpot(out safeSpot, 30, 50, target.Position) && Skills.Wizard.ArchonTeleport.CanCast() && safeSpot != Vector3.Zero && CanTeleportTo(safeSpot))
                    {
                        //Util.Logger.LogError("10码精英");
                        return Teleport(safeSpot);
                    }
                }

                // 使用溃解光波
                if (Skills.Wizard.ArchonDisintegrationWave.CanCast())
                {
                    //Logger.Log("使用溃解光波攻击目标");
                    return ArchonDisintegrationWave(target);
                }

                return null;
            }

            // 使用黑洞
            if (Skills.Wizard.BlackHole.CanCast() && Core.Player.PrimaryResource > 18)
            {
                if (Skills.Wizard.BlackHole.CurrentRune == Runes.Wizard.Spellsteal || Skills.Wizard.BlackHole.CurrentRune == Runes.Wizard.AbsoluteZero)
                {
                    if (TargetUtil.NumMobsInRangeOfPosition(target.Position, 15) > Skills.Wizard.BlackHole.BuffStacks)
                    {
                        lastBlackHolePosition = target.Position;
                        return BlackHole(target);
                    }
                }

                if (target.Position.Distance2D(lastBlackHolePosition) > 10)
                {
                    lastBlackHolePosition = target.Position;
                    return BlackHole(target);
                }

                if (Skills.Wizard.BlackHole.TimeSinceUse > 2000)
                {
                    lastBlackHolePosition = target.Position;
                    return BlackHole(target);
                }
            }


            // Use the blizzard
            if (Skills.Wizard.Blizzard.CanCast() && Player.PrimaryResource > 40)
            {

                if (target.Position.Distance2D(lastBlizzardPosition) > 10)
                {
                    lastBlizzardPosition = target.Position;
                    return Blizzard(target);
                }

                if (Skills.Wizard.Blizzard.TimeSinceUse > 6000) {
                    lastBlizzardPosition = target.Position;
                    return Blizzard(target);
                }
            }


            // 使用奥术洪流
            if (Skills.Wizard.ArcaneTorrent.CanCast() && Player.PrimaryResource > 14)
            {
                return ArcaneTorrent(target);
            }


            return Walk(Player.Position);
        }

        public static HashSet<int> ArchonSkillIds = new HashSet<int>
        {
            135166, 135238, 135663, 166616, 167355, 167648, 392883, 392884, 392885, 392886, 392887, 392888, 392889, 392890, 392891,
        };

        internal static bool IsArchonGalvanizingWardGone()
        {
            return Core.Hotbar.ActivePowers.Any(p => ArchonSkillIds.Contains((int)p)) && Core.Player.ShieldHitpoints < GetGalvanizingWardShieldHitpoints();
        }

        internal static double GetArchonBuffRemaining()
        {
            double remaining = 0;
            foreach (CachedBuff buff in Core.Buffs.ActiveBuffs)
            {
                if (buff.SNOPower == SNOPower.Wizard_Archon)
                {
                    remaining = Math.Max(remaining, buff.Remaining.TotalMilliseconds);
                }
            }
            return remaining;
        }

        internal static double GetGalvanizingWardShieldHitpoints()
        {
            double hp = Core.Player.CurrentHealth;
            double max = 0;

            if (Passives.Wizard.GalvanizingWard.IsActive)
            {
                max += hp * 1.1f;
            }

            return max;
        }

        public TrinityPower GetDefensivePower()
        {
            return null;
        }

        public TrinityPower GetBuffPower()
        {
            // 御法者未激活
            if (!IsArchonActive)
            {
                // 使用三刀甲
                if (!Skills.Wizard.EnergyArmor.IsBuffActive && Skills.Wizard.EnergyArmor.CanCast())
                {
                    return EnergyArmor();
                }

                // 使用魔法武器
                if (!Skills.Wizard.MagicWeapon.IsBuffActive && Skills.Wizard.MagicWeapon.CanCast())
                {
                    return MagicWeapon();
                }

                // 使用御法者
                if (Skills.Wizard.Archon.CanCast() && !Core.Player.IsInTown)
                {
                    return Archon();
                }
            }
            // 御法者已激活
            else
            {
                // 使用时间延缓
                if (!IsArchonSlowTimeActive && Skills.Wizard.ArchonSlowTime.CanCast())
                {
                    return ArchonSlowTime();
                }


                // 如果移动中，使用闪电冲击
                if (Core.Player.IsMoving && Skills.Wizard.ArchonBlast.CanCast())
                {
                    return ArchonBlast();
                }

            }
            return null;
        }

        public TrinityPower GetDestructiblePower()
        {
            // 如果御法者已经激活
            if (IsArchonActive)
            {
                if (Skills.Wizard.ArchonBlast.CanCast() && CurrentTarget != null && CurrentTarget.Distance < 15)
                {
                    return ArchonBlast();
                }
            }
            // 如果御法者未激活
            else
            {
                // 使用奥术洪流
                if (Skills.Wizard.ArcaneTorrent.CanCast() && CurrentTarget != null && CurrentTarget.Distance < 15)
                {
                    return ArcaneTorrent(CurrentTarget);
                }
            }

            return DefaultDestructiblePower();
        }


        public TrinityPower GetMovementPower(Vector3 destination)
        {
            if (Skills.Wizard.Teleport.CanCast() || (IsArchonActive && Skills.Wizard.ArchonTeleport.CanCast()))
            {
                var distance = destination.Distance(Player.Position);
                if (!Core.Avoidance.InCriticalAvoidance(destination) && (distance > 15f || (IsBlocked && distance > 5f)))
                    return Teleport(destination);
            }

            if (IsInCombat && !IsArchonActive && (IsBlocked || IsStuck))
            {
                TrinityPower power = GetOffensivePower();
                if (power != null)
                    return power;
            }

            return Walk(destination);
        }
        #endregion

        #region Settings
        public override int ClusterSize
        {
            get
            {
                if (IsArchonActive)
                    return Settings.ClusterSize;
                else
                    return 3;
            }
        }

        IDynamicSetting IRoutine.RoutineSettings => Settings;
        public override float EmergencyHealthPct => Settings.EmergencyHealthPct;
        public MyPralysisArchonBlizzardSettings Settings { get; } = new MyPralysisArchonBlizzardSettings();
        public sealed class MyPralysisArchonBlizzardSettings : NotifyBase, IDynamicSetting
        {
            private SkillSettings _teleport;
            private int _clusterSize;
            private float _emergencyHealthPct;

            [DefaultValue(6)]
            public int ClusterSize
            {
                get { return _clusterSize; }
                set { SetField(ref _clusterSize, value); }
            }

            [DefaultValue(0.6f)]
            public float EmergencyHealthPct
            {
                get { return _emergencyHealthPct; }
                set { SetField(ref _emergencyHealthPct, value); }
            }

            public SkillSettings Teleport
            {
                get { return _teleport; }
                set { SetField(ref _teleport, value); }
            }


            #region Skill Defaults

            private static readonly SkillSettings TeleportDefaults = new SkillSettings
            {
                UseMode = UseTime.Default,
                RecastDelayMs = 200,
                Reasons = UseReasons.Blocked
            };

            #endregion

            public override void LoadDefaults()
            {
                base.LoadDefaults();
                Teleport = TeleportDefaults.Clone();
            }

            #region IDynamicSetting

            public string GetName() => GetType().Name;
            public UserControl GetControl() => UILoader.LoadXamlByFileName<UserControl>(GetName() + ".xaml");
            public object GetDataContext() => this;
            public string GetCode() => JsonSerializer.Serialize(this);
            public void ApplyCode(string code) => JsonSerializer.Deserialize(code, this, true);
            public void Reset() => LoadDefaults();
            public void Save() { }

            #endregion
        }

        #endregion
    }
}


